package com.chenfan.process.config.job;

import com.alibaba.fastjson.JSONObject;
import com.chenfan.infra.constants.CommonBeanConstants;
import com.chenfan.infra.context.TenantContextHolder;
import com.chenfan.notify.NotifyClient;
import com.chenfan.notify.vo.NotifyVo;
import com.chenfan.privilege.client.PrivilegeClient;
import com.chenfan.privilege.vo.STenantRes;
import com.chenfan.process.common.utils.PushUtil;
import com.chenfan.process.entity.po.ApprovalPo;
import com.chenfan.process.entity.po.ApprovalTemplatePo;
import com.chenfan.process.entity.po.ProcessNotifyPo;
import com.chenfan.process.enums.BooleanEnum;
import com.chenfan.process.service.ApprovalService;
import com.chenfan.process.service.ApprovalTemplateService;
import com.chenfan.process.service.ProcessNotifyService;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Slf4j
@Component
public class MessageCheckXxlJob {

    @Value("${notify.alarm.threshold}")
    public int times;
    @Value("${notify.alarm.token}")
    public String token;

    private final Map<Long, Integer> countMap = new ConcurrentHashMap<>();

    @Autowired
    private ProcessNotifyService processNotifyService;
    @Autowired
    private ApprovalTemplateService approvalTemplateService;
    @Autowired
    private ApprovalService approvalService;
    @Autowired
    private NotifyClient notifyClient;
    @Autowired
    private PrivilegeClient privilegeUserServer;

    @XxlJob("checkMessage")
    public ReturnT<String> checkMessage(String param) {

        List<STenantRes> list = Optional.ofNullable(privilegeUserServer.getAllTenantList()).map(x -> x.getObj()).orElse(Collections.emptyList());
        for(STenantRes res: list) {
            MDC.put(CommonBeanConstants.TENANT_ID, res.getTenantId().toString());
            TenantContextHolder.setTenantId(res.getTenantId());
            Map<Long, ApprovalTemplatePo> templateMap = approvalTemplateService.list().stream().collect(Collectors.toMap(ApprovalTemplatePo::getId, e -> e, (e1, e2) -> e2));

            List<ProcessNotifyPo> unArrivalMessage = processNotifyService.getUnArrivalMessage();
            if (CollectionUtils.isEmpty(unArrivalMessage)) {
                continue;
            }
            List<ProcessNotifyPo> updateMessageList = new ArrayList<>();

            // 审批ID, 去查询.
            List<Long> approvalIdList =
                    unArrivalMessage.stream().map(ProcessNotifyPo::getApprovalId).collect(Collectors.toList());
            // 找不到数据说明不是该租户下的.
            List<ApprovalPo> approvalList = approvalService.findApprovalList(approvalIdList);
            if (CollectionUtils.isEmpty(approvalList)) {
                continue;
            }
            Map<Long, List<NotifyVo>> notifyMap = notifyClient.listNotifyByApprovalId(approvalIdList).getObj().stream()
                    .collect(Collectors.groupingBy(NotifyVo::getApprovalId));


            Map<Long, ApprovalPo> approvalMap = approvalList.stream().collect(Collectors.toMap(ApprovalPo::getApprovalId, e -> e));

            for (ProcessNotifyPo processNotify : unArrivalMessage) {
                //
                ApprovalPo approvalPo = approvalMap.getOrDefault(processNotify.getApprovalId(), new ApprovalPo());

                List<NotifyVo> notifyList = notifyMap.getOrDefault(processNotify.getApprovalId(), Collections.emptyList());
                if (CollectionUtils.isEmpty(notifyList) && !approvalPo.isFinish()) {
                    // 如果缺失的话.
                    countMap.putIfAbsent(processNotify.getId(), 0);
                    Integer threshold = countMap.computeIfPresent(processNotify.getId(), (k, v) -> v = v + 1);
                    ApprovalTemplatePo approvalTemplatePo = templateMap.getOrDefault(processNotify.getApprovalTemplateId(), new ApprovalTemplatePo());
                    if (threshold >= times) {
                        log.info("模板id:{}, 获取到的结果:{}, 集合:{}", processNotify.getApprovalTemplateId(), JSONObject.toJSONString(approvalTemplatePo), JSONObject.toJSONString(templateMap));
                        PushUtil.getInstance().send(PushUtil.PushType.DINGDING, token,
                                String.format("生成待办失败, 审批实例ID:%s, 模板ID:%s, 模板Code: %s, 模板标题: %s, 审批人ID:%s, 审批人:%s",
                                        processNotify.getApprovalId(),
                                        processNotify.getApprovalTemplateId(),
                                        approvalTemplatePo.getCode(),
                                        approvalTemplatePo.getTitle(),
                                        processNotify.getApprovalUserId(),
                                        processNotify.getApprovalUserName()));
                        countMap.remove(processNotify.getId());
                        // 告警后有问题的数据
                        processNotify.setStatus(2);
                        updateMessageList.add(processNotify);
                    }
                } else {
                    // 开始检查. 是有命中的.
                    boolean match =
                            notifyList.stream().anyMatch(e -> e.getUserId().equals(processNotify.getApprovalUserId()));
                    if (match) {
                        processNotify.setStatus(BooleanEnum.Y.getCode());
                        updateMessageList.add(processNotify);
                        countMap.remove(processNotify.getId());
                    }
                }
            }
            if (!CollectionUtils.isEmpty(updateMessageList)) {
                processNotifyService.updateBatchById(updateMessageList);
            }
            MDC.clear();
            TenantContextHolder.clear();
        }
        return ReturnT.SUCCESS;
    }
}